﻿#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

//
//class Time
//{
//public:
//	Time(int hour)
//		:_hour(hour)
//	{
//		cout << "Time(int hour)" << endl;
//	}
//private:
//	int _hour;
//};
//
//
//class Date
//{
//public:
//	Date(int& x, int year = 1999, int month = 1, int day = 1)
//		:_year(year)
//		, _month(month)
//		, _day(day)
//		, _t(12)
//		, ref(x)
//		, i(day)
//	{
//		cout << "Date(int& x, int year = 1999, int month = 1, int day = 1)" << endl;
//	}
//
//	void print()const
//	{
//		cout << _year << "-" << _month << "-" << _day << endl;
//	}
//
//private:
//	int _year;
//	int _month;
//	int _day;
//	int& ref;//引用类型的成员变量
//	const int i;//const修饰的成员变量
//	Time _t;  //没有默认构造函数的成员变量
//};

//int main()
//{
//	int i = 10;
//	Date d1(i,2025,3,12);
//	d1.print();
//	return 0;
//}

//
//class A
//{
//public:
//	//1
//	//explicit A(int a1) 我们加上explicit关键字后，就可以使其不能够进行隐式类型转换了
//	A(int a1)
//		:_a1(a1)
//	{
//		cout << "A(int a1)" << endl;
//	}
//	//2
//	A(int a1, int a2)
//		:_a1(a1)
//		, _a2(a2)
//	{
//		cout << "A(int a1, int a2)" << endl;
//	}
//
//	A(const A& a)
//	{
//		cout << "A(const A& a)" << endl;
//	}
//
//	~A()
//	{
//		cout << "~A()" << endl;
//	}
//	void print()const
//	{
//		cout << _a1 << " " << _a2 << endl;
//	}
//
//	int Get()const
//	{
//		return _a1 + _a2;
//	}
//
//private:
//	int _a1 = 1;
//	int _a2 = 2;
//};
//
//class B
//{
//public:
//	B(const A& a)
//		:_b(a.Get())
//	{
//		cout << "B(const A& a)" << endl;
//	}
//private:
//	int _b = 1;
//};
//
//
//int main()
//{
//	//1
//	//这个对象实例化时调用的是第一个只有一个参数的构造函数，由于第一个构造函数中的参数是aa1于是它实例化传参初始化的是aa1
//	A aa1 =5;//5是整型，会构造生成一个临时对象来存储5，然后再进行拷贝构造传给aa1，
//	//因此上面的操作是构造+拷贝构造但是编译器默认优化成一步了直接构造，某种意义上是一种隐式类型转换
//	aa1.print();//5 2(aa1按照传参给的值进行赋值，aa2编译器没有进行赋值于是就按照成员变量声明时的值进行初始化
//
//	//由于const具有常性，所以我们要先生成一个临时对象来暂时保存一下由整型1类型转换生成的A类类型的临时变量
//	const A& aa2 = 1;
//
//	// C++11之后才⽀持多参数转化 
//	//2
//	A aa3 = { 2,2 };//这个对象实例化调用的是上面那个有两个参数的构造函数
//	aa3.print();
//
//	// aa3隐式类型转换为b对象 
//	// 原理跟上⾯类似 
//	//B类显示实现的构造函数里面的参数是一个const类型的，它对于普通的参数权限是更小的，
//	// 因此我们可以将权限更大的（非const修饰）以及权限相等的（有const修饰的）传参给b,但是我们最终都要转换为const A&类型的
//	B b = aa3;
//	//引用也具有常性，我们也要通过临时对象去传参
//	const B& rb = aa3;
//	return 0;
//}
//
//#include<iostream>
//using namespace std;
//class A
//{
//public:
////构造函数
//	A()
//	{
//		++_scount;
//		cout << "A()" << endl;
//	}
////拷贝构造函数
//	A(const A& t)
//	{
//		++_scount;
//		cout << "A(const A& t)" << endl;
//	}
////析构函数
//	~A()
//	{
//		--_scount;
//		cout << "~A()" << endl;
//	}
////静态成员函数
//	static int GetACount()
//	{
//		return _scount;
//	}
//private:
//	// 类⾥⾯声明 
//	//静态成员变量，注意我们不能在静态成员变量声明处给缺省值，也不能在类中进行初始化，必须在类外进行初始化
//	static int _scount;
//};
//
//// 类外⾯初始化 
//int A::_scount = 0;
//
//int main()
//{
//	cout << A::GetACount() << endl;//直接调用A类中的成员函数，由于只有A的构造与析构，没有拷贝构造，因此_scount不变
//
//	A a1, a2;//实例化两个对象变量，因此自动调用了两次构造函数
//	A a3(a1);//这里运用了一次拷贝构造函数
//	//以下两种是突破类域的访问方式：1.类名：：  2.对象名.
//	cout << A::GetACount() << endl;
//	cout << a1.GetACount() << endl;
//	//至于析构函数是在最后进行调用的（函数销毁后，进行一些内存的清理时调用的）
//	// 编译报错：error C2248: “A::_scount”: ⽆法访问 private 成员(在“A”类中声明) 
//	//cout << A::_scount << endl;发生报错是因为静态成员变量也受到public,private,protected等修饰词的限制
//	return 0;
//}
//   
//
//class A
//{
//public:
//	A()
//	{
//		cout << "A()" << endl;
//	}
//
//	~A()
//	{
//		cout << "~A()" << endl;
//	}
//
//
//
//	static int sum;
//
//};
//
//int  A::sum = 10;
//
//int main()
//{
//	A a1;
//	//以下两种访问方式，要在public下才可以进行访问，private下是不可以进行访问的
//	cout << A::sum << endl;
//	cout << a1.sum << endl;
//	return 0;
//}



////友元函数修饰（friend)是一种突破类域访问的方式
//#include<iostream>
//using namespace std;
//// 前置声明，都则A的友元函数声明编译器不认识B 
//class B;
////进行一个类的声明，和我们之前写函数的声明放在头文件里面是一样的，在一个文件中的代码，不同的位置不同的声明位置也是不一样的，
////放在后面的函数，前面的函数如果要用，要事先声明一下
//class A
//{
//	// 友元声明 （可以在任何位置进行声明，可以在中间，可以在前面可以在后面，不过我们一般都放在前面声明，是一个好的书写习惯）
//	friend void func(const A& aa, const B& bb);
//private:
//	int _a1 = 1;
//	int _a2 = 2;
//};
//class B
//{
//	// 友元声明 
//	friend void func(const A& aa, const B& bb);
//private:
//	int _b1 = 3;
//	int _b2 = 4;
//};
//
////这个函数是上面两个类的友元函数，上面两个类中都有该函数的友元函数声明
////友元函数可以在类外进行访问私有制成员变量
//void func(const A& aa, const B& bb)
//{
//	cout << aa._a1 << endl;
//	cout << bb._b1 << endl;
//}
//int main()
//{
//	A aa;
//	B bb;
//	func(aa, bb);//1 3
//	return 0;
//}
//
//
//#include<iostream>
//using namespace std;
//class A
//{
//	// 友元声明 （友元类，将B类使用friend修饰，于是B类就变成了A类的友元类，于是B类就可以访问A类中的私有成员变量）
//	//但是我们要注意：A类不是B类的友元类，在A类中不能访问B类中的私有制成员变量。友元类是单向的，友元类是不可以传递的
//	friend class B;
//	//下面这个函数会发生报错，因为在A类中无法访问B类的成员变量
//	//void func3(const A& aa)
//	//{
//	//	cout << aa._a1 << endl;//1
//	//	cout << _b1 << endl;//3
//	//}
//
//private:
//	int _a1 = 1;
//	int _a2 = 2;
//};
//
//
////在上面已经进行了友元类的声明，于是下面在B类中就可以访问A类中的成员变量
//class B
//{
//public:
//	void func1(const A& aa)
//	{
//		cout << aa._a1 << endl;//1
//		cout << _b1 << endl;//3
//	}
//	void func2(const A& aa)
//	{
//		cout << aa._a2 << endl;//2
//		cout << _b2 << endl;//4
//	}
//private:
//	int _b1 = 3;
//	int _b2 = 4;
//};
//int main()
//{
//	A aa;
//	B bb;
//	bb.func1(aa);//1 3
//	cout << endl;
//	bb.func2(aa);//2 4
//	//cout << endl;
//	//aa.fun3(bb);
//	return 0;
//}
//
//#include<iostream>
//using namespace std;
//class A
//{
//private:
//	static int _k;
//	int _h = 1;
//public:
//
//	//B类定义在A类中，于是我们就将B类叫做A类的内部类，我们会一般默认B就是A的友元类，B中的成员函数可以调用A类中的成员变量
//	//内部类是一个独立的类，不过是一个类定义在另一个类中。如果放在private/protected中就是那个类的私有类
//	class B // B默认就是A的友元 
//	{
//	public:
//		void foo(const A& a)
//		{
//			cout << _k << endl; //OK
//			cout << a._h << endl; //OK
//		}
//	};
//};
//int A::_k = 1;
//int main()
//{
//	cout << sizeof(A) << endl;//计算类A的大小，注意：计算类大小的方式与计算结构体的方式是一样的，它们都是要进行内存对齐的方式进行计算的
//	//由于在A类中只有两个成员变量，还有一个B类，B类中只有成员函数。我们计算类大小时，只计算成员变量的大小，不计算成员函数的大小，
//	// 而且静态成员变量是放在静态区的，不是在类中的，因此也不计算在类的大小中
//	A::B b;//实例化一个对象变量，由于我们实例化的是一个B类对象，但是B类是放在A类中的，于是我们想要实例化调用时，要通过A类进行访问
//	A aa;//实例化一个A类对象
//	b.foo(aa);//使用B类中的一个对象变量来调用B类中的成员函数，由于B类是在A类中定义的，因此它可以调用A类中的私有制成员变量作为参数
//	return 0;
//}

//class A
//{
//public:
//	A(int a = 0)
//		:_a(a)
//	{
//		cout << "A(int a)" << endl;
//	}
//
//	~A()
//	{
//		cout << "~A()" << endl;
//	}
//private:
//	int _a;
//};
//
//class Solution
//{
//public:
//	int Sum_Solution(int n)
//	{
//		//...
//		return n;
//	}
//};
//int main()
//{
//	//匿名对象与有名对象，不仅是定义的方式不一样，而且两者定义对象的生命周期也是不一样的，匿名对象的生命周期很短，在调用构造函数后紧跟着就调用了析构函数
//	//至于有名对象，在我们实例化对象时，编译器自动调用构造函数，在最后进行销毁空间清理内存时才会调用析构函数，而且调用的顺序是后定义的先调用
//	A aa1;
//	cout << endl;
//	// 不能这么定义对象，因为编译器⽆法识别下⾯是⼀个函数声明，还是对象定义 
//	//A aa1();
//	
//	// 但是我们可以这么定义匿名对象，匿名对象的特点不⽤取名字， 
//	// 但是他的⽣命周期只有这⼀⾏，我们可以看到下⼀⾏他就会⾃动调⽤析构函数 
//	//定义匿名对象：类名（），在（）内可以传参数
//
//	A();
//	cout << endl;
//
//	A(1);
//	cout << endl;
//
//
//	A aa2(2);//这个是直接构造有名对象，这个与上面第一个是一样的，由于这么我们显示实现的构造函数里面有一个缺省参数，所以我们写不写参数都是可以的
//	cout << endl;
//
//	// 匿名对象在这样场景下就很好⽤，当然还有⼀些其他使⽤场景，这个我们以后遇到了再说 
//	cout << Solution().Sum_Solution(100) << endl;
//	return 0;
//}


//#include<iostream>
//using namespace std;
//class A
//{
//public:
//
//	A(int a = 0)
//		:_a1(a)
//	{
//		cout << "A(int a)" << endl;
//	}
//
//
//	A(const A& aa)
//		:_a1(aa._a1)
//	{
//		cout << "A(const A& aa)" << endl;
//	}
//
//	A& operator=(const A& aa)
//	{
//		cout << "A& operator=(const A& aa)" << endl;
//		if (this != &aa)
//		{
//			_a1 = aa._a1;
//		}
//		return *this;
//	}
//
//	~A()
//	{
//		cout << "~A()" << endl;
//	}
//private:
//	int _a1 = 1;
//};
//
//void f1(A aa)
//{}
//
//A f2()
//{
//	A aa;
//	return aa;
//}
//int main()
//{
//	// 传值传参 
//	A aa1;
//	f1(aa1);
//	cout << endl;
//	// 隐式类型，连续构造+拷⻉构造->优化为直接构造 
//	f1(1);
//	// ⼀个表达式中，连续构造+拷⻉构造->优化为⼀个构造 
//	//先匿名构造一个对象，然后再构造一个临时对象，然后再拷贝构造，最终都直接优化成一个构造了
//	f1(A(2));
//	cout << endl;
//	cout << "***********************************************" << endl;
//	// 传值返回 
// // 返回时⼀个表达式中，连续拷⻉构造+拷⻉构造->优化⼀个拷⻉构造 （vs2019 debug） 
// // ⼀些编译器会优化得更厉害，进⾏跨⾏合并优化，直接变为构造。（vs2022 debug） 
//	f2();
//	cout << endl;
//	// 返回时⼀个表达式中，连续拷⻉构造+拷⻉构造->优化⼀个拷⻉构造 （vs2019 debug） 
//	// ⼀些编译器会优化得更厉害，进⾏跨⾏合并优化，直接变为构造。（vs2022 debug） 
//	A aa2 = f2();//直接跳过构造实例化aa，构造生成aa2，然后再拷贝构造，在vs2022中优化成直接构造生成一个aa2
//	cout << endl;
//	// ⼀个表达式中，连续拷⻉构造+赋值重载->⽆法优化 
//	aa1 = f2();//直接构造aa，然后赋值运算符重载
//	cout << endl;
//	return 0;
//}

//
//#include <iostream>
//
//class MyClass {
//public:
//    MyClass() 
//    {
//        std::cout << "MyClass constructor called!" << std::endl;
//    }
//};
//
//class StaticClass
//{
//public:
//    static MyClass staticObj;
//
//    StaticClass() {
//        std::cout << "StaticClass constructor called!" << std::endl;
//    }
//};
//
//MyClass StaticClass::staticObj; // 静态成员初始化
//
//int main() 
//{
//    MyClass regularObj; // 创建普通对象
//    std::cout << endl;
//    StaticClass obj; // 创建静态类的对象
//    return 0;
//}
